package srzy.socket

import scala.actors.Actor
import scala.actors.Actor._
import scala.actors.TIMEOUT
import java.net.SocketTimeoutException
import srzy.common.Logging
import srzy.common.Config
import srzy.diameter._
import srzy.rb._
import srzy.common.Common

class RBReceActor(rbMsgActor: RBMsgActor) extends Actor with Logging {

  override def act = {
    while (true) {
      //      reactWithin(1000) {
      //      receiveWithin(1000) {
      //        case 'exit => {
      //          sender ! 'ok
      //          exit()
      //        }
      //        case TIMEOUT =>
      //          {
      try {
        val msg = rbMsgActor.socketConn.read
        getMsgType(msg) match {
          case CODE_KAR => {
            logger.debug("heartbeat rece :" + msg)
            rbMsgActor.socketConn.replyHeartbeat
            //            logger.debug("heartbeat rece :" + msg)
            //            val heartMsg = RBMsgActor.heartMsg.replaceAll(":TIME",
            //              Common.getSysTime("yyyyMMddhhmmssSS"))
            //            rbMsgActor.socketConn.write(heartMsg)
          }
          case CODE_ECA => {
            logger.debug("authentication rece")
          }
          case i: Int => {
            logger.debug("service msg rece [" + i + "]")
            rbMsgActor ! ('rece, msg)
          }
        }
      } catch {
        case ste: SocketTimeoutException =>
      }

      //          }
      //      }
    }
  }

  override def exceptionHandler = {
    case ioe: java.io.IOException => {
      logger.error(ioe.getMessage(), ioe)
      sys.exit
    }
    case e: Exception => logger.error(e.getMessage(), e)
  }

}

class RBMsgActor(getRBSocket: => java.net.Socket) extends Actor with Logging {

  val socketConn: RBSocketConn = new RBSocketConn {
    val socket = getRBSocket
    val outStream = socket.getOutputStream()
    val inStream = socket.getInputStream()
  }

  var oc: scala.actors.OutputChannel[Any] = null
  var rbReceActor: RBReceActor = null

  override def act = {
    loop {
      react {
        case sendMsg: String => {
          if (oc == null) {
            socketConn.write(sendMsg)
            oc = sender
          } else {
            logger.error("The message has not been returned, please waiting for the return")
          }
        }
        case ('rece, receMsg: String) => {
          oc ! receMsg
          oc = null
        }
        case 'exit => {
          (rbReceActor !! 'exit).apply
          socketConn.close
          sender ! 'ok
          exit()
        }
        case a: Any => logger.error("unknown pattern " + a.toString)
      }
    }
  }

  def authentication = {
    socketConn.write(RBSocketConn.ECRMsg)
    logger.debug("AuthenticationReq write over!")
    val msg = socketConn.read()
    val errCode = Integer.parseInt(getErrorCode(msg))

    if (errCode != 0) {
      throw new Exception("Authentication failure : " + srzy.rb.getSessionId(msg))
    }
    logger.info("Authentication success")
    logger.info("Authentication msg : " + msg)
  }

  override def start(): Actor = synchronized {
    super.start()
    this.authentication
    rbReceActor = new RBReceActor(RBMsgActor.this)
    rbReceActor.start
    RBMsgActor.this
  }

  override def exceptionHandler = {
    case ioe: java.io.IOException => {
      logger.error(ioe.getMessage(), ioe)
      sys.exit
    }
    case e: Exception => logger.error(e.getMessage(), e)
  }

}

object RBMsgActor {

  val port = Integer.parseInt(Config.getValue("root", "config", "RB_Port"))
  val ip = Config.getValue("root", "config", "RB_IP")

  def getRBSocket = try {
    SocketConn.connect(ip, port)
  } catch {
    case ex: Exception =>
      ex.printStackTrace()
      exit()
  }

  val actor = new RBMsgActor(getRBSocket)
  //  actor.start

  def apply() = actor

}